From 7a1c5845ef6f579763d3493106ce4b17bfd5d103 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 22 Nov 2014 11:41:24 -0500 Subject: [PATCH] inspector: Show object title in the properties tab Replace the search bar with a search entry in a stack to make this work without unseemly height changes. --- gtk/inspector/prop-list.c | 152 ++++++++++++++++++++++++++++++------- gtk/inspector/prop-list.ui | 51 ++++++++++++- 2 files changed, 171 insertions(+), 32 deletions(-) diff --git a/gtk/inspector/prop-list.c b/gtk/inspector/prop-list.c index aa8837eafd..cefce2fc2c 100644 --- a/gtk/inspector/prop-list.c +++ b/gtk/inspector/prop-list.c @@ -33,7 +33,9 @@ #include "gtktreeview.h" #include "gtktreeselection.h" #include "gtkpopover.h" -#include "gtksearchbar.h" +#include "gtksearchentry.h" +#include "gtklabel.h" +#include "gtkstack.h" enum { @@ -64,46 +66,131 @@ struct _GtkInspectorPropListPrivate GtkTreeViewColumn *attribute_column; GtkWidget *tree; GtkWidget *search_entry; - GtkWidget *search_bar; + GtkWidget *search_stack; + GtkWidget *object_title; }; G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorPropList, gtk_inspector_prop_list, GTK_TYPE_BOX) +static void +search_close_clicked (GtkWidget *button, + GtkInspectorPropList *pl) +{ + gtk_entry_set_text (GTK_ENTRY (pl->priv->search_entry), ""); + gtk_stack_set_visible_child_name (GTK_STACK (pl->priv->search_stack), "title"); +} + +static gboolean +is_keynav_event (GdkEvent *event) +{ + GdkModifierType state = 0; + guint keyval; + + if (!gdk_event_get_keyval (event, &keyval)) + return FALSE; + + gdk_event_get_state (event, &state); + + if (keyval == GDK_KEY_Tab || keyval == GDK_KEY_KP_Tab || + keyval == GDK_KEY_Up || keyval == GDK_KEY_KP_Up || + keyval == GDK_KEY_Down || keyval == GDK_KEY_KP_Down || + keyval == GDK_KEY_Left || keyval == GDK_KEY_KP_Left || + keyval == GDK_KEY_Right || keyval == GDK_KEY_KP_Right || + keyval == GDK_KEY_Home || keyval == GDK_KEY_KP_Home || + keyval == GDK_KEY_End || keyval == GDK_KEY_KP_End || + keyval == GDK_KEY_Page_Up || keyval == GDK_KEY_KP_Page_Up || + keyval == GDK_KEY_Page_Down || keyval == GDK_KEY_KP_Page_Down || + ((state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) != 0)) + return TRUE; + + /* Other navigation events should get automatically + * ignored as they will not change the content of the entry + */ + return FALSE; +} + +static void +preedit_changed_cb (GtkEntry *entry, + GtkWidget *popup, + gboolean *preedit_changed) +{ + *preedit_changed = TRUE; +} + static gboolean key_press_event (GtkWidget *window, GdkEvent *event, GtkInspectorPropList *pl) { - if (gtk_widget_get_mapped (GTK_WIDGET (pl))) + gboolean handled; + gboolean preedit_changed; + guint preedit_change_id; + gboolean res; + gchar *old_text, *new_text; + + if (!gtk_widget_get_mapped (GTK_WIDGET (pl))) + return GDK_EVENT_PROPAGATE; + + if (is_keynav_event (event) || + event->key.keyval == GDK_KEY_space || + event->key.keyval == GDK_KEY_Menu) + return GDK_EVENT_PROPAGATE; + + if (event->key.keyval == GDK_KEY_Return || + event->key.keyval == GDK_KEY_ISO_Enter || + event->key.keyval == GDK_KEY_KP_Enter) { - if (event->key.keyval == GDK_KEY_Return || - event->key.keyval == GDK_KEY_ISO_Enter || - event->key.keyval == GDK_KEY_KP_Enter) + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pl->priv->tree)); + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pl->priv->tree)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - path = gtk_tree_model_get_path (model, &iter); - gtk_tree_view_row_activated (GTK_TREE_VIEW (pl->priv->tree), - path, - pl->priv->name_column); - gtk_tree_path_free (path); - - return GDK_EVENT_STOP; - } - else - return GDK_EVENT_PROPAGATE; + path = gtk_tree_model_get_path (model, &iter); + gtk_tree_view_row_activated (GTK_TREE_VIEW (pl->priv->tree), + path, + pl->priv->name_column); + gtk_tree_path_free (path); + + return GDK_EVENT_STOP; } + else + return GDK_EVENT_PROPAGATE; + } - return gtk_search_bar_handle_event (GTK_SEARCH_BAR (pl->priv->search_bar), event); + if (event->key.keyval == GDK_KEY_Escape) + { + gtk_entry_set_text (GTK_ENTRY (pl->priv->search_entry), ""); + gtk_stack_set_visible_child_name (GTK_STACK (pl->priv->search_stack), "title"); + return GDK_EVENT_STOP; } - else - return GDK_EVENT_PROPAGATE; + + if (!gtk_widget_get_realized (pl->priv->search_entry)) + gtk_widget_realize (pl->priv->search_entry); + + handled = FALSE; + preedit_changed = FALSE; + preedit_change_id = g_signal_connect (pl->priv->search_entry, "preedit-changed", + G_CALLBACK (preedit_changed_cb), &preedit_changed); + + old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (pl->priv->search_entry))); + res = gtk_widget_event (pl->priv->search_entry, event); + new_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (pl->priv->search_entry))); + + g_signal_handler_disconnect (pl->priv->search_entry, preedit_change_id); + + if ((res && g_strcmp0 (new_text, old_text) != 0) || preedit_changed) + { + gtk_stack_set_visible_child_name (GTK_STACK (pl->priv->search_stack), "search"); + handled = TRUE; + } + + g_free (old_text); + g_free (new_text); + + return handled ? GDK_EVENT_STOP : GDK_EVENT_PROPAGATE; } static void @@ -283,8 +370,10 @@ gtk_inspector_prop_list_class_init (GtkInspectorPropListClass *klass) gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, attribute_column); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, tree); gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, search_entry); - gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, search_bar); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, search_stack); + gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, object_title); gtk_widget_class_bind_template_callback (widget_class, row_activated); + gtk_widget_class_bind_template_callback (widget_class, search_close_clicked); } static void @@ -392,6 +481,7 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl, GParamSpec **props; guint num_properties; guint i; + const gchar *title; if (!object) return FALSE; @@ -407,6 +497,12 @@ gtk_inspector_prop_list_set_object (GtkInspectorPropList *pl, return TRUE; } + title = (const gchar *)g_object_get_data (object, "gtk-inspector-object-title"); + gtk_label_set_label (GTK_LABEL (pl->priv->object_title), title); + + gtk_entry_set_text (GTK_ENTRY (pl->priv->search_entry), ""); + gtk_stack_set_visible_child_name (GTK_STACK (pl->priv->search_stack), "title"); + if (pl->priv->child_properties) { GtkWidget *parent; diff --git a/gtk/inspector/prop-list.ui b/gtk/inspector/prop-list.ui index aa1637ff7c..ba717b8319 100644 --- a/gtk/inspector/prop-list.ui +++ b/gtk/inspector/prop-list.ui @@ -13,14 +13,57 @@